var FG;
if (!FG)
    FG = {};

/**
 * 这两个池子是为了使得在任何时候到来的snapshot总有地方可去.
 * FG._snapshotListViewPool是为每个pitem所包含的snapshotList准备的, 而_snapshotViewPool是为每个pitem默认的图标(thumbshot)准备的.
 * 并分别提供一个get函数, 以pitem的uuid为参数(对于默认图标的snapshot与pitem的uuid相同).
 */
FG._snapshotListViewPools = {};
FG._snapshotViewPools = {};
FG.getSnapshotListView = function(uuid) {
    if (!_.has(FG._snapshotListViewPools, uuid)) {
        FG._snapshotListViewPools[uuid] = new FG.SnapshotListView();
    }
    return FG._snapshotListViewPools[uuid];
};
FG.getSnapshotView = function(uuid) {
    if (!_.has(FG._snapshotViewPools, uuid)) {
        FG._snapshotViewPools[uuid] = new FG.SnapshotView({tagName: 'div'});
    }
    return FG._snapshotViewPools[uuid];
};

FG.SnapshotView = DX.BBView.extend({
    tagField: 'uuid',
    tagName: 'li',  // 默认是供列表用的, 给默认图标用的需指定为'div'
    className: 'snapshot',
    prefix: 'snapshot',
    defaultValues: {
        html: '----',
        caption: '----'
    },

    // close按钮需在生成时根据是否是默认图标后加.
    template: _.template(
        '<img src="<%= thumbnail %>" />' +
        '<div class="textthumb"><%= html %></div>' +
        '<div class="caption"><%= caption %></div>'
    ),

    render: function() {
        var defaults = _.clone(this.defaultValues);
        var data = _.extend(defaults, this.model.attributes);
        this.$el.html(this.template(data));
        if (!data.item_default){
            this.$el.append('<div class="close"></div>')
        }
        this.$('.ttblock.varname').textfill({maxFontPixels: 16});
        return this;
    },

    events: {
        //'mouseenter': function(e) {
        //    //DX.warn('enter ss');
        //    this.$el.children('.close').addClass('active');
        //    e.stopPropagation();
        //},
        //'mouseleave': function(e) {
        //    this.$el.children('.close').removeClass('active');
        //    //e.stopPropagation();
        //},
        'click': function(e) {
            DX.warn('click ss');
            if (!this.model)
                return;

            if (this.model.get('item_default') === true) {
            } else {
                var viewport = {
                    type: "snapshot",
                    status: this.model.get('status')
                };
                DX.shout('viewport:switch!', viewport);
                e.stopPropagation();
            };
        },
        'click .close': function(e) {
            DX.shout('snapshot:del!', this.model);
            e.stopPropagation();
        }
    }
});

FG.SnapshotListView = DX.BBCollectionView.extend({
    tagField: 'uuid',
    tagName: 'ul',
    className: 'snapshot_list',

    modelView: FG.SnapshotView,

    events: {
        'mouseleave': function(e){
            DX.error("leaving snapshots");
            this.hide();
            //e.stopPropagation();
        }
    },

    show: function(args) {
        // TODO: 位置偏移更加智能(根据当前css的边界值而定, 以使得出现的位置合理)
        // TODO: 增加在地图widget上合适位置显示的功能.
        args = _.extend({pos: this.pitem.$el.offset()}, args);
        var left = args.pos.left - 2;
        var top = args.pos.top - 2;
        DX.warn(args.pos);
        this.$el.css('left', left).css('top', top).css('display', 'block');
    },

    hide: function() {
        this.$el.css('display', 'none');
    }

});

// ProjectList列表中的单条记录界面
FG.ProjectEntryView = DX.BBView.extend({
    tagField: 'uuid',
    tagName: 'li',
    className: 'project_entry',
    prefix: 'projentry',
    defaultValues: {
        name: "--",
        item_default: false,
        type: "wind",
        desc: "",
        status: ""
    },

    template: _.template(
        '<div class="name"><%= name %></div>' +
        '<div class="icon icon_<%= type %>"></div>' +
        '<div class="desc"><%= desc %></div>' +
        '<div class="status"><%= status %></div>' +
        '<div class="close"></div>'
    ),

    render: function() {
        var defaults = _.clone(this.defaultValues);
        var data = _.extend(defaults, this.model.attributes);
        data.status = '创建: ' + moment(data.create_dt).format('YYYY/MM/DD hh:mm') + '  访问: ' + moment(data.access_dt).format('YYYY/MM/DD hh:mm');
        this.$el.html(this.template(data));
        return this;
    },

    events: {
        'mouseenter': function(e) {
            this.$el.children('.close').addClass('active');
            e.stopPropagation();
        },
        'mouseleave': function(e) {
            this.$el.children('.close').removeClass('active');
            //e.stopPropagation();
        },
        'click .close' : function(e){
            var this_ = this;
            DX.confirm('确定要删除此工程吗?', function() {
                DX.shout('project:del!', this_.model);
            });
            e.stopPropagation();
        },
        'click' : function(e){
            DX.shout('project:switch!', this.model);
            DX.shout('toggle:item_list!');
        }
    }
});

// ProjectList界面
FG.ProjectListView = DX.BBCollectionView.extend({
    tagField: 'uuid',
    el: "#project_list",
    modelView: FG.ProjectEntryView
});

// ProjectItem单条记录界面.
FG.ProjectItemView = DX.BBView.extend({
    tagField: 'uuid',
    tagName: 'li',
    className: 'project_item',
    prefix: 'pitem',
    defaultValues: {
        uuid: '------------',
        name: "----",
        desc: "----"
    },

    template: _.template(
        '<div class="thumbshot" id="pi_thumb_<%= uuid %>">' +
            //'<div class="emblem"></div>' +
        '</div>' +
        '<div class="name"><%= name %></div>' +
        '<div class="desc"><%= desc %></div>' +
        '<div class="itemloading"><i class="fa fa-circle-o-notch fa-spin"></i></div>' +
        '<div class="error" style="display: hidden"></div>' +
        '<div class="minmax"></div>' +
        '<div class="close"></div>'
    ),

    events: {
        //'mouseenter': function(e) {
        //    this.$el.children('.close').addClass('active');
        //    e.stopPropagation();
        //},
        //'mouseleave': function(e) {
        //    this.$el.children('.close').removeClass('active');
        //    //e.stopPropagation();
        //},
        'click .close': function(e){
            var this_ = this;
            e.stopPropagation();
            DX.confirm('确定要删除此条目吗?', function() {
                DX.shout('pitem:del!', this_.model);
            });
        },
        'click .minmax': function(e){
            e.stopPropagation();
            var this_ = this;
            var showing_status = this_.model.get('showing_status');
            showing_status.collapsed = !showing_status.collapsed;
            this_.model.set('showing_status', showing_status);
            this_.model.trigger('change', this_.model);  // TODO:这里先引发了界面变化, 但与后端交互后还会有一次刷新.
            this_.model.save();
            if (!showing_status.collapsed) {
                var uuid = this.model.get('uuid');
                setTimeout(function() {
                    DX.shout('pitem:focus!', uuid);
                    DX.shout('map:goto!', uuid);
                }, 300);
            }
        },
        'click' : function(e) {
            e.stopPropagation();
            if (!this.model) {
                return;
            }
            if (this.model.get('showing_status').collapsed) {
                return;
            }

            var uuid = this.model.get('uuid');
            DX.shout('pitem:focus!', uuid);
            // var viewport = {
            //     type: "pitem",
            //     status: {pitem: this.model.get('uuid')}
            // };
            //
            // if (!!this.defaultSnapshotView.model) {
            //     var snapshot = this.defaultSnapshotView.model.attributes;
            //     if (!!snapshot) {
            //         _.extend(viewport.status, snapshot.status)
            //     }
            // }
            //
            // DX.shout("viewport:switch!", viewport);

            DX.shout("map:goto!", uuid);
        },
        'dblclick' : function(e) {
            var this_ = this;
            e.stopPropagation();
            var showing_status = this_.model.get('showing_status');
            if (!!showing_status.collapsed) {
                showing_status.collapsed = !showing_status.collapsed;
                this_.model.set('showing_status', showing_status);
                this_.model.trigger('change', this_.model); // TODO:这里先引发了界面变化, 但与后端交互后还会有一次刷新.
                this_.model.save();
                var uuid = this.model.get('uuid');
                setTimeout(function() {
                    DX.shout('pitem:focus!', uuid);
                    DX.shout('map:goto!', uuid);
                }, 300);
                return;
            }
        }
    },

    initialize: function () {
        //this.dfd = $.Deferred();
        var uuid = this.model.get('uuid');
        this.snapshotListView = FG.getSnapshotListView(uuid);
        this.snapshotListView.pitem = this;
        this.defaultSnapshotView = FG.getSnapshotView(uuid);
    },

    render: function() {
        var defaults = _.clone(this.defaultValues);
        this.$el.html(this.template(_.extend(defaults, this.model.attributes)));
        this.$(".thumbshot").prepend(this.defaultSnapshotView.$el);
        this.$el.append(this.snapshotListView.$el);
        this.snapshotListView.delegateEvents();
        _.each(this.snapshotListView.entryList, function(ssView) {
            ssView.delegateEvents();
        });
        this.$el.attr('uuid', this.model.get('uuid'));
        this.$el.attr('tag', 'pitem-' + this.model.get('uuid'));
        if (this.model.has('showing_status') && this.model.get('showing_status').collapsed) {
            this.$el.addClass('collapsed');
        }
        if (!!this.model.get('loading')) {
            this.$el.find('.itemloading').show()
        } else {
            this.$el.find('.itemloading').hide()
        }
        var errors = [];
        if (this.model.get('item_type') === 'MultiPolygon' && 
            this.model.has('hasDsvList') &&   // 对于前端刚生成的item, 因为没有走parse的步骤, 所以不会有这个属性.
            !this.model.get('loading') && 
            !this.model.get('hasMapData')) {
            errors.push('<p title="如果是通过搜索框添加的, 请删掉本条目, 重新搜索, 并在点击添加区域图标时按住Ctrl键.">没有地图数据! </p>');
        }
        if (errors.length > 0) {
            var errorStr = errors.join('');
            this.showError(errorStr);
        }
        return this;
    },

    renderEmblem: function(val) {
        // TODO:
        if (typeof val !== 'undefined') {
            // add emblem
        } else {
            // remove emblem
        }
        //var ssNum = this.snapshotListView.entryList.length - 1;
        //if (ssNum > 0) {
        //    this.$(".thumbshot").append($('<div class="emblem">'+String(ssNum)+'</div>'));
        //}
    },

    setFocus: function(status) {
        if (typeof status === 'undefined' || !!status) {
            this.$el.addClass('active');
        } else {
            this.$el.removeClass('active');
        }
    },
    
    showError: function(msg) {
        this.$el.find('.error').html(msg).show();
    },
    
    hideError: function() {
        this.$el.find('.error').hide();
    }
});

// ProjectItemList界面
FG.ProjectItemListView = DX.BBCollectionView.extend({
    tagField: 'uuid',
    //el: "#project_itemlist",
    modelView: FG.ProjectItemView,

    switchProject: function(model) {
        this.clearAll();
        this.project = model;
        this.loadProject(model)
    },

    loadProject: function(model) {
        var this_ = this;
        this.project = model;
        if (!this.project) {
            return;
        }
        if (_.has(this.project, 'itemList')){
            this.project.itemList.each(function(item) {
                this_.pushEntry(item)
            });
        }
    }
});

FG.ProjectItemHeadNeckView = Backbone.View.extend({
    headTemplate: _.template(
        '<div class="normal_head">' +
            '<div class="icon icon_<%= type %>"></div>' +
            '<div class="name_wrapper">' +
                '<div class="label name" title="工程名(点击可修改)"><%= name %></div>' +
            '</div>' +
            '<div class="button_row itemhead_button_row">' +
                '<div class="button setting" title="设置"><i class="fa fa-cog"></i></div>' +
                '<div class="button list" title="切换至工程列表"><i class="fa fa-reorder"></i></div>' +
            '</div>' +
        '</div>' +
        '<div class="edit_head">' +
            '<div class="icon icon_<%= type %>"></div>' +
            '<div class="name_wrapper input_wrapper">' +
                '<input class="label name input" type="text" placeholder="请输入工程名">' +
            '</div>' +
            '<div class="desc_wrapper input_wrapper">' +
                '<textarea class="label desc input" placeholder="请输入工程描述信息"></textarea>' +
            '</div>' +
            '<div class="label status"><%= status %></div>' +
            '<div class="button_row itemhead_button_row">' +
                '<div class="button save" title="保存"><i class="fa fa-check"></i></div>' +
                '<div class="button undo" title="取消"><i class="fa fa-undo"></i></div>' +
            '</div>' +
        '</div>'
    ),
    neckTemplate: _.template(
        '<div class="proj_tools subneck">' +
            '<div class="button_row bigtoolbutton_row">' +
                '<div class="button bigtoolbutton rect_button" title="勾选一个矩形区域">' +
                    '<i class="fa fa-square"></i>' +
                    '<span>矩形</span>' +
                '</div>' +
                '<div class="button bigtoolbutton polygon_button" title="绘制一个多边形区域">' +
                    '<i class="fa fa-bookmark fa-rotate-270"></i>' +
                    '<span>多边形</span>' +
                '</div>' +
                '<div class="button bigtoolbutton point_button" title="新增一个坐标点">' +
                    '<i class="fa fa-map-marker"></i>' +
                    '<span>点</span>' +
                '</div>' +
                //'<div class="button bigtoolbutton line_button">' +
                //    //'<i class="icon-map-marker"></i>' +
                //    '<span>线</span>' +
                //'</div>' +
                //'<div class="button bigtoolbutton polygon_button">' +
                //    '<i class="icon-certificate"></i>' +
                //    '<span>多边形</span>' +
                //'</div>' +
                '<div id="more_func_button" class="button bigtoolbutton" onclick="DX.print(\'Not Implemented\')" style="width:48px">' +
                    //'<i class="icon-map-marker icon-2x"></i>' +
                    '<span style="color:grey; bottom: 14px">更多功能敬请期待</span>' +
                '</div>' +
            '</div>' +
        '</div>' +
        '<div class="proj_settings subneck">' +
            //'<div class="button_row">' +
            //    '<div class="label">设置</div>' +
            //'</div>' +
            '<div class="button_row bigtoolbutton_row">' +
                //'<div id="more_func_button" class="button bigtoolbutton" onclick="DX.print(\'Not Implemented\')" style="width:48px">' +
                //    //'<i class="icon-map-marker icon-2x"></i>' +
                //    '<span style="color:grey; bottom: 14px">更多设置待实现</span>' +
                //'</div>' +
                '<div class="button bigtoolbutton refresh_project" style="float:right" title="刷新">' +
                    '<i class="fa fa-refresh"></i>' +
                    '<span>刷新</span>' +
                '</div>' +
            '</div>' +
        '</div>'
    ),
    render: function() {
        var this_ = this;
        var info = !!this.model ? this.model.attributes : {
            type: '',
            name: ''
        };
        if (!!this.model) {
            info.status = '创建: ' + moment(info.create_dt).format('YYYY/MM/DD hh:mm') + '  访问: ' + moment(info.access_dt).format('YYYY/MM/DD hh:mm');
        } else {
            info.status = ''
        }

        this.$el.children('.head').html(this.headTemplate(info));
        this.$el.find('.edit_head .name').val(info.name);
        this.$el.find('.edit_head .desc').val(info.desc);

        if (!!this.model) {
            this.$el.find('.edit_head .name').unbind('pressEnter').pressEnter(function(e) {
                DX.shout('project:save!');
                e.stopPropagation();
            });
        }

        this.$el.children('.neck').html(this.neckTemplate(info));

        if (!this.neckToggler) {
            this.neckToggler = new DX.Toggler({
                'projTools': this.$el.find('.proj_tools'),
                'projSettings': this.$el.find('.proj_settings')
            }, {
                'default': 'projTools',
                actions: {
                    _all: function() {
                        this_.projectPanel.onResize();
                    }
                }
            });
        } else {
            this.neckToggler.pushEntry('projTools', this.$el.find('.proj_tools'));
            this.neckToggler.pushEntry('projSettings', this.$el.find('.proj_settings'));
            this.neckToggler.refresh();
        }

        if (!this.funcButtonToggler) {
            this.funcButtonToggler = new DX.Toggler({
                'settings': this.$el.find('.head .setting')
            }, {
                onoff: true,
                bindEvents: ['click'],
                actions: {
                    settings: function() {
                        this_.neckToggler.toggle('projSettings')
                    }
                },
                offActions: {
                    settings: function() {
                        this_.neckToggler.toggle('projTools')
                    }
                }
            });
        } else {
            this.funcButtonToggler.pushEntry('settings', this.$el.find('.head .setting'));
            this.funcButtonToggler.refresh();
        }

        if (!this.headToggler) {
            this.headToggler = new DX.Toggler({
                normal: this.$el.find('.normal_head'),
                edit: this.$el.find('.edit_head')
            }, {
                "default": 'normal',
                actions: {
                    _all: function() {
                        this_.projectPanel.onResize();
                    },
                    edit: function() {
                        this_.neckToggler.toggle('none');
                        this_.$el.find('.edit_head .name.input').focus();
                        this_.projectPanel.onResize();
                    },
                    normal: function () {
                        this_.neckToggler.toggle('projTools');
                        this_.projectPanel.onResize();
                    }
                }
            });
        } else {
            this.headToggler.pushEntry('normal', this.$el.find('.normal_head'));
            this.headToggler.pushEntry('edit', this.$el.find('.edit_head'));
            this.headToggler.refresh();
        }

        var drawRectButton = this.$el.find('.rect_button');
        var drawPointButton = this.$el.find('.point_button');
        var drawLineButton = this.$el.find('.line_button');
        var drawPolygonButton = this.$el.find('.polygon_button');
        if (!this.drawFuncToggler){
            this.drawFuncToggler = new DX.Toggler({
                'draw_rect': drawRectButton,
                'draw_point': drawPointButton,
                'draw_line': drawLineButton,
                'draw_polygon': drawPolygonButton
            }, {
                bindEvents:['click'],
                actions: {
                    'draw_rect': function() {DX.shout('start:draw:rect!')},
                    'draw_point': function() {DX.shout('start:draw:point!')},
                    'draw_line': function() {DX.shout('start:draw:line!')},
                    'draw_polygon': function() {DX.shout('start:draw:polygon!')}
                },
                offActions: {
                    'draw_rect': function() {DX.shout('stop:draw:rect!')},
                    'draw_point': function() {DX.shout('stop:draw:point!')},
                    'draw_line': function() {DX.shout('stop:draw:line!')},
                    'draw_polygon': function() {DX.shout('stop:draw:polygon!')}
                },
                onoff: true
            });

            DX.on('draw:end', function() {
                this_.drawFuncToggler.toggle('none')
            })
        } else {
            this.drawFuncToggler.pushEntry('draw_rect', drawRectButton);
            this.drawFuncToggler.pushEntry('draw_point', drawPointButton);
            this.drawFuncToggler.pushEntry('draw_line', drawLineButton);
            this.drawFuncToggler.pushEntry('draw_polygon', drawPolygonButton);
            this.drawFuncToggler.refresh();
        }
        return this;
    },
    events: {
        'click .normal_head .name': function(e) {
            DX.shout('toggle:project_edit!');
            e.stopPropagation();
        },
        'click .normal_head .list': function(e) {
            DX.shout('toggle:project_list!');
            e.stopPropagation();
        },
        'click .edit_head .item': function(e) {
            DX.shout('toggle:item_list!');
            e.stopPropagation();
        },
        'click .edit_head .undo': function(e) {
            this.render();
            DX.shout('toggle:project_normal!');
            e.stopPropagation();
        },
        'click .edit_head .save': function(e) {
            DX.shout('project:save!');
            e.stopPropagation();
        },
        'click .refresh_project': function(e) {
            DX.shout('project:refresh!');
            e.stopPropagation();
        }
    },
    switchProject: function(project) {
        this.model = project;
        this.render();
    },
    getInfo: function() {
        return {
            name: this.$el.find('.edit_head .name').val(),
            desc: this.$el.find('.edit_head .desc').val()
        }
    }
});

FG.ProjectTypeView = DX.BBView.extend({
    tagField: 'name',
    tagName: 'div',
    className: 'button projtype',
    prefix: 'project_type',
    defaultValues: {
        'name': '',
        'desc': '',
        'zh_name': ''
    },
    template: _.template(
        '<i class="icon_<%= name %>"></i><span><%= zh_name %></span>'
    ),
    render: function() {
        var defaults = _.clone(this.defaultValues);
        var data = _.extend(defaults, this.model.attributes);
        this.$el.html(this.template(data));
        this.$el.attr('projtype', data.name);
        this.$el.attr('title', data.desc);
        return this;
    },
    events: {
        'click': function(e) {
            e.stopPropagation();
            DX.shout('projtype:choosed', this.model);
        }
    }
});

FG.ProjectTypeListView = DX.BBCollectionView.extend({
    tagField: 'name',
    modelView: FG.ProjectTypeView
});

// 总体
FG.ProjectPanel = function (opts) {
    var this_ = this;

    this.moduleInfo = {
        name: 'projectPanel',
        zhName: '工程',
        desc: '工程'
    };

    this.opts = _.extend({}, opts);

    if (_.has(this.opts, 'app')) {
        this.app = this.opts.app;
    }

    this.initialize = function() {
        this.project = undefined;

        this.app.toolModer.registerMode('project', 
            function() {this_._setActive()},
            function() {this_._setActive(false)}
        );
        
        var toolPaneContents = '';

        var tabPane = this.app.toolPanel.addTab('project', {
            zhName: this.moduleInfo.zhName,
            tabClass: "sidebar_tab_project",
            tabGroup: "tool",
            iconClass: "fa fa-th-list",
            paneID: 'project_panel',
            paneContents: toolPaneContents,
            enter: function() {
                this_.app.toolModer.toggleMode('project');
                this_.onResize();
                // console.log('Toggle Mode: Project')
            }
        });
    
        this.initView({pane: tabPane.pane});
        this.connectSignals();
        return this;
    };

    this.initView = function(opts){
        this.$el = opts.pane;
        // this.$el.css()
        this.$itemPanel = $(
            '<div class="item_panel subpanel">' +
                '<div class="head">' +
                '</div>' +
                '<div class="neck">' +
                '</div>' +
                '<div class="body nano">' +
                    '<div class="loading"><i class="fa fa-spinner fa-spin fa-2x"></i></div>' +
                    '<div class="hint"><i class="fa fa-level-up fa-flip-horizontal"></i> 请添加所需的区域或坐标点, 或通过屏幕右上方的搜索框搜索地名或经纬度. </div>' +
                    '<ul class="project_itemlist nano-content"></ul>' +
                '</div>' +
            '</div>'
        );
        this.$listPanel = $(
            '<div class="list_panel subpanel">' +
                '<div class="head">' +
                    '<div class="label title">工程列表</div>' +
                    '<div class="button_row listhead_button_row">' +
                        '<div class="button refresh" title="刷新工程列表" onclick="DX.shout(\'projectlist:refresh!\')"><i class="fa fa-refresh"></i></div>' +
                        '<div class="button add" title="添加新工程"><i class="fa fa-plus"></i></div>' +
                        '<div class="button item" title="切换至当前工程内容" onclick="DX.shout(\'toggle:item_list!\')"><i class="fa fa-th-list"></i></div>' +
                    '</div>' +
                '</div>' +
                '<div class="neck">' +
                    '<div class="choose_projtype subneck">' +
                        '<div class="label">新建工程，请选择类型: </div>' +
                        '<div class="button cancel" title="取消新工程创建"><span>取消</span></div>' +
                        '<div class="button_row projtype_list">' +
                            // '<div class="button projtype" projtype="wind"><i class="icon_wind"></i><span>风资源</span></div>' +
                            // '<div class="button projtype" projtype="solar"><i class="icon_solar"></i><span>太阳能</span></div>' +
                            // '<div class="button projtype" projtype="met"><i class="icon_met"></i><span>气象综合</span></div>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
                '<div class="body nano">' +
                    '<div class="loading"><i class="fa fa-spinner fa-spin fa-2x"></i></div>' +
                    '<div class="hint">请添加所需的工程 <i class="fa fa-level-up"></i></div>' +
                    '<ul class="project_list nano-content"></ul>' +
                '</div>' +
            '</div>'
        );
        this.$el.append(this.$itemPanel, this.$listPanel);
        this.panelToggler = new DX.Toggler({
            item: this.$itemPanel,
            list: this.$listPanel
        }, {
            "default": 'list'
        });
        this.$itemBody = this.$itemPanel.children('.body');
        this.$listBody = this.$listPanel.children('.body');
        this.$itemList = this.$itemBody.children('.project_itemlist');
        this.$projectList = this.$listBody.children('.project_list');

        this.$itemLoading = this.$itemBody.find('.loading');
        this.$listLoading = this.$listBody.find('.loading');
        this.$itemHint = this.$itemBody.find('.hint');
        this.$listHint = this.$listBody.find('.hint');

        this.$projtypeChoose = this.$listPanel.find('.neck .choose_projtype');
        this.$projtypeList = this.$projtypeChoose.find('.projtype_list');

        this.listNeckToggler = new DX.Toggler({
            'projtype': this.$projtypeChoose
        }, {
            actions: {
                _all: function() {
                    this_.onResize();
                }
            }
        });
        
        this.projtypeListView = new FG.ProjectTypeListView({
            el: this.$projtypeList
        });

        //var sortable = Sortable.create(this.$itemList[0], {
        //    sort: true,
        //    animation: 150,
        //    handle: '.thumbshot'
        //});

        this.itemHeadNeckView = new FG.ProjectItemHeadNeckView({
            el: this.$itemPanel
        });
        this.itemHeadNeckView.projectPanel = this;
        this.itemHeadNeckView.render();


        this.projectListView = new FG.ProjectListView({el: this.$projectList});
        this.projectItemListView = new FG.ProjectItemListView({el: this.$itemList});

        // not working?
        //this.resizeSensor = new ResizeSensor(this.$el, function(){
        //    this_.onResize();
        //});
        this.onResize();
        this.itemHeadNeckView.headToggler.toggle("normal");
    };

    this.onResize = function() {
        if (!this.$el)
            return;

        if(!!this.$itemPanel) {
            this.$itemPanel.children('.body').height(
                this.$el.height() -
                    this.$itemPanel.children('.head').height() -
                    this.$itemPanel.children('.neck').height()
            );
        }
        if(!!this.$listPanel) {
            this.$listPanel.children('.body').height(
                this.$el.height() -
                this.$listPanel.children('.head').height() -
                this.$listPanel.children('.neck').height()
            );
        }

        this.updateItemListScrollbar();
        this.updateProjectListScrollbar();
    };

    this.addProject = function(info, opts) {
        info = _.extend({name: '未命名工程', desc: '', type: 'wind'}, info);
        opts = _.extend({switchProject: true, toggleView: true, toggleEdit: false}, opts);

        if (!!opts.switchProject){
            DX.once('db:project:update', function(model) {
                DX.shout('project:switch!', model);
            });
        }
        if (!!opts.toggleView) {
            DX.once('db:project:update', function(model){
                this_.panelToggler.toggle('item');
                this_.showHideItemHint();
            });
        }
        if (!!opts.toggleEdit) {
            DX.once('db:project:update', function(model) {
                this_.itemHeadNeckView.headToggler.toggle('edit');
                this_.hideItemHint();
            })
        }

        DX.shout('project:add!', {
            uuid: DX.gen_uuid8(),
            type: info.type,
            name: info.name,
            desc: info.desc
        });
    };

    this.saveProject = function() {
        var info = this.itemHeadNeckView.getInfo();
        if (!this_.project) {
            this_.addProject(info);
        } else {
            this_.project.save({
                name: info.name,
                desc: info.desc
            });
            this_.itemHeadNeckView.headToggler.toggle('normal');
            this_.showHideItemHint();
        }
    };

    this.switchProject = function(model) {
        this_.project = model;
        this_.itemHeadNeckView.switchProject(model);
        this_.projectItemListView.switchProject(model);
        //this_.itemEditHeadView.switchProject(model);
    };

    this.switchViewport = function(viewport) {
        // 切换到所在工程
        // 切换到相应的pitem.
        if (!viewport)
            return;

        if (_.contains(['pitem', 'dsv', 'snapshot'], viewport.type)) {
            if (!!this.currentItemView) {
                this.currentItemView.setFocus(false);
            }
            var pitemUUID = viewport.status.pitem;
            var pitemView = this_.projectItemListView.getByTag(pitemUUID);
            pitemView.setFocus(true);
            this.currentItemView = pitemView;
            this.currentViewport = viewport;
            DX.error(this.currentViewport);
        } else if (viewport.type === 'map') {

        }
    };

    this.updateItemListScrollbar = function() {
        this.$itemBody.nanoScroller();
    };

    this.updateProjectListScrollbar = function() {
        this.$listBody.nanoScroller();
    };

    this.showItemLoading = function() {
        this.hideItemHint();
        this.$itemLoading.show();
    };

    this.hideItemLoading = function() {
        this.$itemLoading.hide();
        this.showHideItemHint();
    };

    this.showListLoading = function() {
        this.hideListHint();
        this.$listLoading.show();
    };

    this.hideListLoading = function() {
        this.$listLoading.hide();
        this.showHideListHint();
    };

    this.showItemHint = function() {
        this.$itemHint.show();
    };

    this.hideItemHint = function() {
        this.$itemHint.hide();
    };

    this.showHideItemHint = function() {
        if (this.itemHeadNeckView.headToggler.value() !== 'normal') {
            this.hideItemHint();
        } else if (this.projectItemListView.entryList.length === 0) {
            this.showItemHint();
        } else {
            this.hideItemHint();
        }
    };

    this.showListHint = function() {
        this.$listHint.show();
    };

    this.hideListHint = function() {
        this.$listHint.hide();
    };

    this.showHideListHint = function() {
        if (this.projectListView.entryList.length === 0) {
            this.showListHint();
        } else {
            this.hideListHint();
        }
    };

    this.focusPItem = function(uuid) {
        var app = this.app;
        // FGView: FeatureGroupView
        pitemFGView = app.mapPanel.getFeatureGroupView('pitem');

        pitemFGView.getAllBut(uuid, function(fview) {
            fview.setFocus(false);
        });
        pitemFGView.getByTag(uuid, function(fview) {
            fview.setFocus();
        });

        this.projectItemListView.getAllBut(uuid, function(v) {
            v.setFocus(false);
        });
        this.projectItemListView.getByTag(uuid, function(v) {
            v.setFocus();
        })
    };

    this._setActive = function(on) {
        if (on === false) {
            // TODO
        } else {
            
        }
    };
    // functions
    this.connectSignals = function() {
        var this_ = this;

        DX.on('viewport:switch!', function(viewport){
            this_.switchViewport(viewport);
        });

        DX.on('db:project:add', function(model) {
            this_.hideListHint();
            this_.projectListView.pushEntry(model);
            this_.updateProjectListScrollbar();
        });

        DX.on('db:project:update', function(model) {
            this_.hideListHint();
            this_.projectListView.pushEntry(model);
            if (!!this_.project && (model.getTag() === this_.project.getTag())) {
                //this_.projectTitleView.render();
                //this_.projectListTitleView.render();
                this_.itemHeadNeckView.model = model;
                //this_.itemEditHeadView.model = model;
                this_.itemHeadNeckView.render();
                //this_.itemEditHeadView.render();
            }
            this_.updateProjectListScrollbar();
        });

        DX.on('db:project:del', function(model) {
            this_.projectListView.deleteEntry(model);
            this_.updateProjectListScrollbar();
            this_.showHideListHint();
        });

        DX.on('db:project:switch', function(model) {
            this_.switchProject(model);
            DX.set('project:loaded', true);
        });
    
        DX.on('db:ptype:add', function(model) {
            this_.projtypeListView.pushEntry(model);
        });
        
        DX.on('db:ptype:update', function(model) {
            this_.projtypeListView.pushEntry(model); 
        });
        
        DX.on('db:ptype:del', function(model) {
            this_.projtypeListView.deleteEntry(model);
        });
        
        DX.on('toggle:item_list!', function() {
            if (!this_.project) {
                DX.alert("请先创建或选择一个工程");
            } else {
                this_.panelToggler.toggle("item");
            }
        });

        DX.on('toggle:project_list!', function() {
            this_.panelToggler.toggle("list");
            this_.showHideListHint();
        });

        DX.on('toggle:project_edit!', function() {
            this_.hideItemHint();
            this_.itemHeadNeckView.headToggler.toggle('edit');
        });

        DX.on('toggle:project_normal!', function() {
            this_.itemHeadNeckView.headToggler.toggle('normal');
            this_.showHideItemHint();
        });

        //DX.on('toggle:project_settings!', function() {
        //    this_.itemHeadfuncButtonToggler.toggle();
        //});

        DX.on('db:pitem:add', function(model) {
            this_.hideItemHint();
            this_.projectItemListView.pushEntry(model);
            this_.updateItemListScrollbar();
        });

        DX.on('db:pitem:update', function(model) {
            this_.hideItemHint();
            this_.projectItemListView.pushEntry(model);
            this_.updateItemListScrollbar();
        });

        DX.on('db:pitem:del', function(model) {
            this_.projectItemListView.deleteEntry(model);
            this_.updateItemListScrollbar();
            this_.showHideItemHint();
        });

        DX.on('pitem:focus!', function(uuid) { this_.focusPItem(uuid); });
        
        DX.on('db:snapshot:add', function(model) {
            var pitem_uuid = model.get('project_item_uuid');
            var ssListView = FG.getSnapshotListView(pitem_uuid);
            ssListView.pushEntry(model);
            if (model.get('item_default')) {
                var ssView = FG.getSnapshotView(pitem_uuid);
                ssView.model = model;
                ssView.render();
                //ssView.delegateEvents();
            }
            DX.set('lastSnapshot', model.attributes);
        });

        DX.on('db:snapshot:change', function(model) {
            var pitem_uuid = model.get('project_item_uuid');
            var ssListView = FG.getSnapshotListView(pitem_uuid);
            ssListView.pushEntry(model);
            if (model.get('item_default')) {
                var ssView = FG.getSnapshotView(pitem_uuid);
                ssView.model = model;
                ssView.render();
                //ssView.delegateEvents();
            }
            DX.set('lastSnapshot', model.attributes);
        });

        DX.on('db:snapshot:del', function(model) {
            var pitem_uuid = model.get('project_item_uuid');
            var ssListView = FG.getSnapshotListView(pitem_uuid);
            ssListView.deleteEntry(model);
        });

        // html 事件转发
        // TODO, this one may be !
        DX.on('widget:snapshots:expand', function(opts) {
            //var pitemView = this_.projectItemListView.getByUUID(opts.uuid);
            var ssListView = FG.getSnapshotListView(opts.uuid);
            ssListView.show({pos: opts.pos})
        });

        DX.on('project:save!', function() {
            this_.saveProject();
        });

        DX.on('datapack:reloaded', function(uri) {
            DX.warn("Got datapack:reloaded: " + uri);
            DX.warn("Switching viewport: ");
            DX.print(this_.currentViewport);
            DX.shout('viewport:switch!', DX.get('lastSnapshot'));
        });

        DX.on('window:resized', function() {
            this_.onResize();
        });

        DX.on('db:projectlist:load:begin', function() {
            this_.showListLoading();
        });

        DX.on('db:projectlist:load:end', function() {
            this_.hideListLoading();
        });

        DX.on('db:project:load:begin', function() {
            this_.showItemLoading();
        });

        DX.on('db:project:load:end', function() {
            this_.hideItemLoading();
        });

        $('#project_panel').find('.list_panel .head .button.add').click(function (e) {
            //this_.addProject({name: '未命名工程', desc: ''}, {toggleEdit:true});
            this_.listNeckToggler.toggle('projtype');
            this_.hideListHint();
            e.stopPropagation();
        });

        $('#project_panel').find('.list_panel .choose_projtype .button.cancel').click(function (e) {
            this_.listNeckToggler.toggle('none');
            this_.onResize();
            this_.showHideListHint();
            e.stopPropagation();
        });
        
        DX.on('projtype:choosed', function(ptype) {
            var ptypeData = _.has(ptype, 'attributes') ? ptype.attributes : ptype;
            this_.addProject({name: '未命名工程', desc: '', type: ptypeData.name}, {toggleEdit: true});
            this_.listNeckToggler.toggle('none');
            this_.onResize();
        });
    };
};

